'use client'

import { Chip, ChipProps } from '@nextui-org/chip'

import { Tooltip } from '@nextui-org/tooltip'
import React from 'react'
import { columns, statusOptions, users } from './data'
import NextIcon from '@/components/NextIcon'
import { Link } from '@nextui-org/link'
import {
  Button,
  Dropdown,
  DropdownItem,
  DropdownMenu,
  DropdownTrigger,
  Input,
  Pagination,
  Selection,
  User,
  Select,
  SelectItem
} from '@nextui-org/react'
import { capitalize } from './utils'
import Table from './Table'

const statusColorMap: Record<string, ChipProps['color']> = {
  active: 'success',
  paused: 'danger',
  vacation: 'warning'
}

const pageOptions = ['5', '10', '20', '50']

const INITIAL_VISIBLE_COLUMNS = ['name', 'role', 'status', 'actions']

type User = (typeof users)[0]

const UserManagerPage = () => {
  const [filterValue, setFilterValue] = React.useState('')
  const [selectedKeys, setSelectedKeys] = React.useState<Selection>(new Set([]))
  const [statusFilter, setStatusFilter] = React.useState<Selection>('all')
  const [visibleColumns, setVisibleColumns] = React.useState<Selection>(
    new Set(INITIAL_VISIBLE_COLUMNS)
  )

  const [page, setPage] = React.useState(1)
  const [rowsPerPage, setRowsPerPage] = React.useState(5)

  const hasSearchFilter = Boolean(filterValue)

  const headerColumns = React.useMemo(() => {
    if (visibleColumns === 'all') return columns

    return columns.filter(column =>
      Array.from(visibleColumns).includes(column.uid)
    )
  }, [visibleColumns])

  const renderAction = (item?: any, key?: string, uid?: string) => {
    return (
      <div className="flex justify-center">
        <div className="relative flex items-center gap-2">
          <Tooltip content="Details">
            <span className="text-lg text-default-400 cursor-pointer active:opacity-50">
              <NextIcon type="eye" size={16} />
            </span>
          </Tooltip>
          <Tooltip content="Edit user">
            <span className="text-lg text-default-400 cursor-pointer active:opacity-50">
              <NextIcon type="edit-fill" size={16} />
            </span>
          </Tooltip>
          <Tooltip color="danger" content="Delete user">
            <span className="text-lg text-danger cursor-pointer active:opacity-50">
              <NextIcon type="delete" size={16} />
            </span>
          </Tooltip>
        </div>
      </div>
    )
  }

  const renderCell = React.useCallback((user: User, columnKey: React.Key) => {
    const cellValue = user[columnKey as keyof User]

    switch (columnKey) {
      case 'name':
        return (
          <User
            avatarProps={{ radius: 'lg', src: user.avatar }}
            description={user.email}
            name={cellValue}
          >
            <Link href={`mailto:${user.email}`}>{user.email}</Link>
          </User>
        )
      case 'role':
        return (
          <div className="flex flex-col">
            <p className="text-bold text-small capitalize">{cellValue}</p>
            <p className="text-bold text-tiny capitalize text-default-400">
              {user.team}
            </p>
          </div>
        )
      case 'status':
        return (
          <Chip
            className="capitalize"
            color={statusColorMap[user.status]}
            size="sm"
            variant="flat"
          >
            {cellValue}
          </Chip>
        )
      case 'actions':
        return renderAction(user, String(user.id), columnKey)
      default:
        return cellValue
    }
  }, [])

  const onClear = React.useCallback(() => {
    setFilterValue('')
    setPage(1)
  }, [])

  const onSearchChange = React.useCallback((value?: string) => {
    if (value) {
      setFilterValue(value)
      setPage(1)
    } else {
      setFilterValue('')
    }
  }, [])

  const onRowsPerPageChange = React.useCallback((size: number) => {
    setRowsPerPage(size)
    setPage(1)
  }, [])

  const filteredItems = React.useMemo(() => {
    let filteredUsers = [...users]

    if (hasSearchFilter) {
      filteredUsers = filteredUsers.filter(user =>
        user.name.toLowerCase().includes(filterValue.toLowerCase())
      )
    }
    if (
      statusFilter !== 'all' &&
      Array.from(statusFilter).length !== statusOptions.length
    ) {
      filteredUsers = filteredUsers.filter(user =>
        Array.from(statusFilter).includes(user.status)
      )
    }

    return filteredUsers
  }, [users, filterValue, statusFilter])

  const items = React.useMemo(() => {
    const start = (page - 1) * rowsPerPage
    const end = start + rowsPerPage

    return filteredItems.slice(start, end)
  }, [page, filteredItems, rowsPerPage])

  const pages = React.useMemo(
    () => Math.ceil(filteredItems.length / rowsPerPage),
    [filteredItems, rowsPerPage]
  )

  const topContent = React.useMemo(() => {
    return (
      <div className="flex flex-col gap-4">
        <div className="block sm:flex justify-between sm:gap-3 gap-4 items-end">
          <Input
            isClearable
            className="w-full sm:max-w-[44%]"
            placeholder="Search by name..."
            startContent={<NextIcon type="search" />}
            value={filterValue}
            onClear={() => onClear()}
            onValueChange={onSearchChange}
          />
          <div className="block sm:flex sm:gap-3 gap-4 max-sm:mt-4">
            <div className="flex space-x-4">
              <Dropdown>
                <DropdownTrigger className="flex-1">
                  <Button
                    endContent={<NextIcon type="down" className="text-small" />}
                    variant="flat"
                  >
                    Status
                  </Button>
                </DropdownTrigger>
                <DropdownMenu
                  disallowEmptySelection
                  aria-label="Table Columns"
                  closeOnSelect={false}
                  selectedKeys={statusFilter}
                  selectionMode="multiple"
                  onSelectionChange={setStatusFilter}
                >
                  {statusOptions.map(status => (
                    <DropdownItem key={status.uid} className="capitalize">
                      {capitalize(status.name)}
                    </DropdownItem>
                  ))}
                </DropdownMenu>
              </Dropdown>
              <Dropdown>
                <DropdownTrigger className="flex" title="表头筛选">
                  <Button isIconOnly color="default" title="表头筛选">
                    <NextIcon type="filter" size={16} />
                  </Button>
                </DropdownTrigger>
                <DropdownMenu
                  disallowEmptySelection
                  aria-label="Table Columns"
                  closeOnSelect={false}
                  selectedKeys={visibleColumns}
                  selectionMode="multiple"
                  onSelectionChange={setVisibleColumns}
                >
                  {columns.map(column => (
                    <DropdownItem key={column.uid} className="capitalize">
                      {capitalize(column.name)}
                    </DropdownItem>
                  ))}
                </DropdownMenu>
              </Dropdown>
              <Button
                color="primary"
                className="flex-1"
                endContent={<NextIcon type="plus" />}
              >
                Add New
              </Button>
            </div>
          </div>
        </div>
      </div>
    )
  }, [
    filterValue,
    statusFilter,
    visibleColumns,
    onSearchChange,
    onRowsPerPageChange,
    hasSearchFilter
  ])

  const bottomContent = React.useMemo(() => {
    return (
      <div className="py-2 mt-4 flex justify-center items-center space-x-4">
        <Pagination
          loop
          showControls
          showShadow
          page={page}
          total={pages}
          onChange={setPage}
        />

        <div className="flex justify-between items-center">
          <label className="flex items-center text-default-400 text-small">
            <Select
              aria-label="Table Columns"
              selectedKeys={new Set([String(rowsPerPage)])}
              className="w-[70px]"
              classNames={{
                trigger: 'h-9 min-h-9'
              }}
              onChange={e =>
                onRowsPerPageChange(
                  e.target.value ? Number(e.target.value) : 10
                )
              }
            >
              {pageOptions.map(animal => (
                <SelectItem key={animal}>{animal}</SelectItem>
              ))}
            </Select>
          </label>
        </div>

        <div className="flex justify-between items-center">
          <span className="text-default-400 text-small">
            Total: {filteredItems.length}
          </span>
        </div>
      </div>
    )
  }, [
    selectedKeys,
    filteredItems.length,
    page,
    pages,
    hasSearchFilter,
    rowsPerPage
  ])

  return (
    <div className="mb-6">
      {topContent}

      <Table
        columns={headerColumns}
        items={items}
        renderCell={renderCell}
        selectedKeys={selectedKeys}
        setSelectedKeys={setSelectedKeys}
      />

      {bottomContent}
    </div>
  )
}

export default UserManagerPage
